﻿namespace Awsc.DataAcquisitionSys.Core.Common.Expressions;
public class ValueComparer
{

    public static bool Compare(object obj1, object obj2, OperatorType op)
    {
        // 处理 null 情况
        if (obj1 == null && obj2 == null)
        {
            return op == OperatorType.Equal ||
                   op == OperatorType.GreaterThanOrEqual ||
                   op == OperatorType.LessThanOrEqual;
        }
        if (obj1 == null || obj2 == null)
        {
            return op switch
            {
                OperatorType.NotEqual => true,
                _ => false
            };
        }

        // 处理 bool 类型比较
        if (obj1 is bool b1 && obj2 is bool b2)
        {
            return op switch
            {
                OperatorType.Equal => b1 == b2,
                OperatorType.NotEqual => b1 != b2,
                OperatorType.LessThanOrEqual=>b1==b2,
                OperatorType.GreaterThanOrEqual=>b1==b2,
                _ => throw new InvalidOperationException($"Bool值不支持 \"{op}\" 操作符")
            };
        }

        // 数值类型比较
        if (IsNumericType(obj1) && IsNumericType(obj2))
        {
            return CompareNumerics(obj1, obj2, op);
        }

        // 相同类型比较
        if (obj1.GetType() == obj2.GetType() && obj1 is IComparable comparable1)
        {
            int comparisonResult = comparable1.CompareTo(obj2);
            return op switch
            {
                OperatorType.Equal => comparisonResult == 0,
                OperatorType.NotEqual => comparisonResult != 0,
                OperatorType.GreaterThan => comparisonResult > 0,
                OperatorType.GreaterThanOrEqual => comparisonResult >= 0,
                OperatorType.LessThan => comparisonResult < 0,
                OperatorType.LessThanOrEqual => comparisonResult <= 0,
                _ => throw new ArgumentException($"不支持的比较符 \"{op}\".")
            };
        }

        // 默认使用 Equals 进行相等性检查
        bool areEqual = obj1.Equals(obj2);
        return op switch
        {
            OperatorType.Equal => areEqual,
            OperatorType.NotEqual => !areEqual,
            _ => throw new InvalidOperationException($"不能使用比较符 \"{op}\" 比较  \"{obj1.GetType().Name}\"类型 和 \"{obj2.GetType().Name}\"类型 .")
        };
    }

    private static bool IsNumericType(object obj)
    {
        if (obj == null) return false;
        Type type = obj.GetType();

        return Type.GetTypeCode(type) switch
        {
            TypeCode.Byte or TypeCode.SByte or TypeCode.UInt16 or TypeCode.UInt32 or TypeCode.UInt64 or
            TypeCode.Int16 or TypeCode.Int32 or TypeCode.Int64 or TypeCode.Decimal or TypeCode.Double or
            TypeCode.Single => true,
            _ => false
        };
    }

    private static bool CompareNumerics(object obj1, object obj2, OperatorType op)
    {
        // 处理 decimal 类型
        if (obj1 is decimal || obj2 is decimal)
        {
            decimal d1 = Convert.ToDecimal(obj1);
            decimal d2 = Convert.ToDecimal(obj2);
            return op switch
            {
                OperatorType.Equal => d1 == d2,
                OperatorType.NotEqual => d1 != d2,
                OperatorType.GreaterThan => d1 > d2,
                OperatorType.GreaterThanOrEqual => d1 >= d2,
                OperatorType.LessThan => d1 < d2,
                OperatorType.LessThanOrEqual => d1 <= d2,
                _ => false
            };
        }

        // 处理 double/float 类型
        if (obj1 is double || obj2 is double ||
            obj1 is float || obj2 is float)
        {
            double d1 = Convert.ToDouble(obj1);
            double d2 = Convert.ToDouble(obj2);

            // 处理浮点数精度问题
            const double tolerance = 1e-10;
            return op switch
            {
                OperatorType.Equal => Math.Abs(d1 - d2) < tolerance,
                OperatorType.NotEqual => Math.Abs(d1 - d2) > tolerance,
                OperatorType.GreaterThan => d1 > d2,
                OperatorType.GreaterThanOrEqual => d1 >= d2 || Math.Abs(d1 - d2) < tolerance,
                OperatorType.LessThan => d1 < d2,
                OperatorType.LessThanOrEqual => d1 <= d2 || Math.Abs(d1 - d2) < tolerance,
                _ => false
            };
        }

        // 处理整数类型
        long l1 = Convert.ToInt64(obj1);
        long l2 = Convert.ToInt64(obj2);
        return op switch
        {
            OperatorType.Equal => l1 == l2,
            OperatorType.NotEqual => l1 != l2,
            OperatorType.GreaterThan => l1 > l2,
            OperatorType.GreaterThanOrEqual => l1 >= l2,
            OperatorType.LessThan => l1 < l2,
            OperatorType.LessThanOrEqual => l1 <= l2,
            _ => false
        };
    }
}